package com.gcxy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gcxy.constant.StringConst;
import com.gcxy.core.PageVO;
import com.gcxy.core.R;
import com.gcxy.dto.role.AddRoleDTO;
import com.gcxy.dto.role.UpdateRoleDTO;
import com.gcxy.dto.role.RolePageDTO;
import com.gcxy.entity.*;
import com.gcxy.mapper.*;
import com.gcxy.service.ResourceService;
import com.gcxy.service.RoleService;
import com.gcxy.utils.BeanCopyUtil;
import com.gcxy.vo.resource.ResourceVO;
import com.gcxy.vo.role.RoleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author pep7chiao
 * @date 2024/7/7
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private ResourceRoleMapper resourceRoleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ResourceService resourceService;

    /**
     * 获取所有角色
     *
     * @return 获取所有角色
     */
    @Override
    public List<RoleVO> getAllRoles() {
        List<Role> roles = roleMapper.selectList(null);
        List<RoleVO> roleVOList = new ArrayList<>();
        // 设置每一个角色对象
        for (Role role : roles) {
            List<ResourceVO> resourceVOList = resourceService.getResourceByRoleId(role.getId());
            RoleVO roleVO = BeanCopyUtil.copy(role, RoleVO.class);
            roleVO.setResourceVOList(resourceVOList);
            roleVOList.add(roleVO);
        }
        return roleVOList;
    }

    /**
     * 更新角色信息
     *
     * @param updateRoleDTO 角色对象
     * @return 前端返回对象
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public R<Void> updateRole(UpdateRoleDTO updateRoleDTO) {
        Integer roleId = updateRoleDTO.getId();
        String roleName = updateRoleDTO.getRoleName();
        //判断是否是不能修改的用户
        if (roleId == StringConst.SUPER_ADMIN) {
            return R.Failed("该角色为超级管理员，不能修改！");
        }
        //判断名字不能修改的用户
        if ((roleId == StringConst.TEACHER && !StringConst.TEACHER_NAME.equals(roleName))
                || (roleId == StringConst.STUDENT && !StringConst.STUDENT_NAME.equals(roleName))
                || (roleId == StringConst.AGENCY_ADMIN && !StringConst.AGENCY_ADMIN_NAME.equals(roleName)
        )) {
            return R.Failed("该角色为默认角色，名称不能修改！");
        }
        //判断重复
        LambdaQueryWrapper<Role> queryName = new LambdaQueryWrapper();
        queryName.eq(!ObjectUtils.isEmpty(roleName), Role::getRoleName, roleName);
        List<Role> roles = roleMapper.selectList(queryName);
        if (!ObjectUtils.isEmpty(roles) && roles.size() > 1) {
            return R.Failed("操作失败，角色名字重复！");
        }
        Role role = BeanCopyUtil.copy(updateRoleDTO, Role.class);
        // 复制当前角色对象
        int row = roleMapper.updateById(role);
        // 根据刷新资源角色关系表，重新绑定关系
        if (updateRoleDTO.getResourceList() != null) {
            resourceRoleMapper.delete(new QueryWrapper<ResourceRole>().eq("role_id", updateRoleDTO.getId()));
            for (Integer resourceId : updateRoleDTO.getResourceList()) {
                if (resourceId > 0) {
                    ResourceRole resourceRole = new ResourceRole();
                    resourceRole.setRoleId(updateRoleDTO.getId());
                    resourceRole.setResourceId(resourceId);
                    resourceRoleMapper.insert(resourceRole);
                }
            }
        }
        if (row > 0) {
            return R.Success("角色信息更新成功");
        }
        return R.Failed("角色信息更新失败");
    }

    /**
     * 删除指定的角色
     *
     * @param roleId 角色ID
     * @return 前端返回对象
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public R<Void> deleteRoleById(Integer roleId) {
        //角色如果是超级管理员,老师,学生,机构管理员不能删除
        if (roleId == StringConst.SUPER_ADMIN || roleId == StringConst.TEACHER
                || roleId == StringConst.STUDENT || roleId == StringConst.AGENCY_ADMIN) {
            return R.Failed("该角色为默认角色，不能删除！");
        }
        //
        List<UserRole> userRoleList = userRoleMapper.selectList(new QueryWrapper<UserRole>().eq("role_id", roleId));
        List<User> userList = new ArrayList<>();
        //判断角色是否关联用户
        if (userRoleList != null && userRoleList.size() > 0) {
            //获取用户列表
            for (UserRole userRole : userRoleList) {
                User user = userMapper.selectById(userRole.getUserId());
                userList.add(user);
            }
            return R.Failed("删除失败，有关联用户！", userList);
        }
        // 删除资源角色表对应的数据
        resourceRoleMapper.delete(new QueryWrapper<ResourceRole>().eq("role_id", roleId));
        // 删除角色表中对应的数据
        int row = roleMapper.deleteById(roleId);
        if (row > 0) {
            return R.Success("角色删除成功");
        }
        return R.Failed("角色删除失败");
    }

    /**
     * 新增角色
     *
     * @param addRoleDTO 角色数据传递对象a
     * @return 前端返回对象
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public R<Void> insertRole(AddRoleDTO addRoleDTO) {
        //判断重复
        String roleName = addRoleDTO.getRoleName();
        if (verifyDuplicates(roleName)) return R.Failed("操作失败，角色名字重复！");
        //插入角色
        Role role = BeanCopyUtil.copy(addRoleDTO, Role.class);
        int row = roleMapper.insert(role);
        if (row > 0) {
            // 插入角色的相关资源
            //查询角色资源关系
            List<Integer> resourceList = addRoleDTO.getResourceList();
            if (resourceList != null) {
                for (Integer resourceId : resourceList) {
                    ResourceRole resourceRole = new ResourceRole();
                    resourceRole.setRoleId(role.getId());
                    resourceRole.setResourceId(resourceId);
                    resourceRoleMapper.insert(resourceRole);
                }
            }
            return R.Success("新增角色成功");
        }
        return R.Failed("新增角色失败");
    }

    /**
     * 验证角色名是否重复
     *
     * @param roleName 被验证的角色名
     * @return 验证结果
     */
    private boolean verifyDuplicates(String roleName) {
        LambdaQueryWrapper<Role> queryName = new LambdaQueryWrapper();
        queryName.eq(!ObjectUtils.isEmpty(roleName), Role::getRoleName, roleName);
        Role repeatedNameRole = roleMapper.selectOne(queryName);
        if (!ObjectUtils.isEmpty(repeatedNameRole)) {
            return true;
        }
        return false;
    }

    /**
     * 根据条件分页查询角色
     *
     * @param rolePageDTO 查询条件
     * @return 查询结果
     */
    @Override
    public PageVO getRolePageByCondition(RolePageDTO rolePageDTO) {

        //根据查询条件查询分页查询角色信息
        List<Role> roleList = resourceRoleMapper.selectResourceRolesPageByCondition(rolePageDTO);
        PageVO<RoleVO> roleVOPageVO = new PageVO(rolePageDTO.getPageNo().longValue(), rolePageDTO.getPageSize().longValue());
        roleVOPageVO.setTotal(Long.valueOf(roleList.size()));
        //如果查询结果不为空，则把列表根据分页条件进行过滤条数
        if (!ObjectUtils.isEmpty(roleList)) {
            roleList = roleList.stream()
                    .skip((long) (rolePageDTO.getPageNo() - 1) * rolePageDTO.getPageSize()) // 跳过前面的元素
                    .limit(rolePageDTO.getPageSize()) // 限制结果集的大小
                    .collect(Collectors.toList()); // 收集结果到一个新的列表
        }
        List<RoleVO> roleVOList = null;
        if (!ObjectUtils.isEmpty(roleList)) {
            roleVOList = new ArrayList<>();
            for (Role role : roleList) {
                List<ResourceVO> resourceVOS = BeanCopyUtil.copyList(role.getResources(), ResourceVO.class);
                RoleVO roleVO = BeanCopyUtil.copy(role, RoleVO.class);
                roleVO.setResourceVOList(resourceVOS);
                roleVOList.add(roleVO);
            }
        }
        roleVOPageVO.setRecords(roleVOList);
        Long pages = roleVOPageVO.getTotal() % rolePageDTO.getPageSize() == 0 ? roleVOPageVO.getTotal() / rolePageDTO.getPageSize() : roleVOPageVO.getTotal() / rolePageDTO.getPageSize() + 1;
        roleVOPageVO.setPages(pages);
        return roleVOPageVO;
    }

}
